Micron Document
Deavmi's coding shack


Commit 47f33d26103ca8ef96849cbf9a5dbb6b3b310e8e


Parents : c177a95
Author : Tristan Brice Velloza Kildaire <deavmi@redxen.eu>
Date : 2026-05-05T11:25:39+02:00

added siome todos

Changes

3 files changed, 211 insertions(+), 33 deletions(-)

M monitor.go +76 -31
A out +133

Diff

diff --git a/manager_test.go b/manager_test.go
index f033089..121a622 100644
--- a/manager_test.go
+++ b/manager_test.go
@@ -11,7 +11,7 @@ func Test_deps(t *testing.T) {
// create dependency `a` which depends on `b`
// and load it
a := New("a")
- a.command = "/bin/yes"
+ a.command = "/bin/ping"
a.args = []string{"google.com", "-c", "10"}
a.AddDep("b")
m.Load(a)
@@ -19,7 +19,7 @@ func Test_deps(t *testing.T) {
// create dependency `b` which depends on `c`
// and load it
b := New("b")
- b.command = "/bin/yes"
+ b.command = "/bin/ping"
b.args = []string{"yahoo.com", "-c", "9"}
b.AddDep("c")
m.Load(b)

diff --git a/monitor.go b/monitor.go
index 510e1cf..b8d4ec6 100644
--- a/monitor.go
+++ b/monitor.go
@@ -2,15 +2,20 @@ package main
import (
"context"
+ "errors"
"fmt"
"io"
"os"
"os/exec"
+ "reflect"
+ "strings"
"sync"
"new.git.deavmi.assigned.network/deavmi/glog.git/std/consts"
stdlogger "new.git.deavmi.assigned.network/deavmi/glog.git/std/logger"
"new.git.deavmi.assigned.network/deavmi/go-niknaks.git/slices"
+
+ "new.git.deavmi.assigned.network/deavmi/go-niknaks.git/types"
)
func (b Bruh) Name() string {
@@ -75,6 +80,7 @@ func (b *Bruh) Start() error {
// this means when WE receive a cancel we can
// get it but so will all derived contexts
var e *exec.Cmd = exec.CommandContext(b.ctx, b.u.command, b.u.args...)
+ b.cmd = e
b.log.Trace("b.u.command: %v", b.u.command)
// install environment variables
@@ -112,17 +118,9 @@ func (b *Bruh) Start() error {
NewPipeMonitor(b, std_err, b.ctx, b.log).Start()
}
- // after this c.Process becomes non-nil and we should
- // release resources (when process is done, via e.Wait()?)
- if s_e := e.Start(); s_e != nil {
- b.log.Error("Error starting process for '%s': %v", b.u.Name(), s_e)
- return fmt.Errorf("Error starting process for '%s': %v", b.u.Name(), s_e)
- }
- var proc *os.Process = e.Process
- b.log.Debug("Process PID %d for '%s'...", proc.Pid, b.u.Name())
-
// schedule a goroutine here with the monitor
- // function
+ // function - this will start the process and
+ // monitor it
go b.monitor()
return nil
@@ -145,19 +143,77 @@ func NewPipeMonitor(monitor *Bruh, r io.ReadCloser, ctx context.Context, log *st
return PipeMonitor{m: monitor, pipe: r, ctx: ctx, log: log}
}
+// user-requested stop
+func (b *Bruh) Stop() {
+ // TODO: Set custom error with Is support
+}
+
+// signal
+// Stop the process
+//
+// 1. calls `Kill()`
+// 2. cancels the `b.ctx`
+// 2.1 this unblocks Goroutine running `monitor()`
+// 2.2 this causes the process in `b.cmd.process` to kill the process
+func (b *Bruh) stop(cause error) {
+ b.log.Info("Stopping '%s' for reason '%v'...", b.Name(), cause)
+ // TODO: Implement me
+ // Shutdown log monitors?
+ // Kill the process? (Only if the reason we were called was not that)
+ if !errors.Is(cause, types.Zero[ProcessStartFailureReason]()) {
+ // Only kill it if it actually started
+ }
+}
+
+type ProcessStartFailureReason struct {
+ internalReason error
+ path string
+ args []string
+}
+
+func (psfr ProcessStartFailureReason) Error() string {
+ var s string
+ if len(psfr.args) != 0 {
+ s = strings.Join(psfr.args, " ")
+ }
+ return fmt.Sprintf("Process '%s%s'start failed: %v", psfr.path, s, psfr.internalReason)
+}
+
+func (psfr ProcessStartFailureReason) Is(e error) bool {
+ return reflect.TypeOf(e) == reflect.TypeFor[ProcessStartFailureReason]()
+}
+
func (b *Bruh) monitor() {
- // wait for us to be cancelled
- select {
- case <-b.ctx.Done():
- b.log.Info("Got closing signal: %v", context.Cause(b.ctx))
+ // after this c.Process becomes non-nil and we should
+ // release resources (when process is done, via e.Wait()?)
+ if s_e := b.cmd.Start(); s_e != nil {
+ b.log.Error("Error starting process for '%s': %v", b.u.Name(), s_e)
+ // Request stop
+ b.stop(ProcessStartFailureReason{internalReason: s_e, path: b.cmd.Path, args: b.cmd.Args})
+ return
}
+ var proc *os.Process = b.cmd.Process
+ b.log.Debug("Process PID %d for '%s'...", proc.Pid, b.u.Name())
+
+ // wait for us to be cancelled
+ // select {
+ // case <-b.ctx.Done():
+ // b.log.Info("Got closing signal: %v", context.Cause(b.ctx))
+ // }
// TODO: Perform shutdown
- b.log.Trace("Shutting down pipes...")
- for p_idx, p := range b.pipes {
- b.log.Trace("(%d) Shutting down pipe '%v'...", p_idx, p)
- p.Stop()
- }
+ // b.log.Trace("Shutting down pipes...")
+ // for p_idx, p := range b.pipes {
+ // b.log.Trace("(%d) Shutting down pipe '%v'...", p_idx, p)
+ // p.Stop()
+ // }
+
+ // wait for process to end
+ p, e := proc.Wait()
+
+ // when it ends, call stop (once again with a custom reason)
+ // Determine this based on `p` (exit, or signal)
+ b.log.Trace("ProcessState after exit: %v (%v)", p, e)
}
const BUFFER_SIZE = 1000
@@ -230,7 +286,7 @@ func (b *PipeMonitor) logMonitor() {
}
}
- b.log.Trace("Log monitor for '%s' on fd '%v' using buffer size %d", BUFFER_SIZE)
+ b.log.Trace("Log monitor for '%s' on fd '%v' using buffer size %d", b.m.Name(), b.pipe, BUFFER_SIZE)
var buff []byte = make([]byte, BUFFER_SIZE)
for {
@@ -269,17 +325,6 @@ func (b *PipeMonitor) logMonitor() {
}
}
-// signal
-// Stop the process
-//
-// 1. calls `Kill()`
-// 2. cancels the `b.ctx`
-// 2.1 this unblocks Goroutine running `monitor()`
-// 2.2 this causes the process in `b.cmd.process` to kill the process
-func (b *Bruh) Stop() {
-
-}
-
func (m *Bruh) makeEnvs(u Unit) []string {
var vars []string
for k, v := range u.GetEnvs() {

diff --git a/out b/out
new file mode 100644
index 0000000..e7326a1
--- /dev/null
+++ b/out
@@ -0,0 +1,133 @@
+Added dependency 'b' to a
+u: Unit[a] (deps: [b]) @
+Never encountered 'a' before, caching...
+Stored unit Unit[a] (deps: [b]) @
+Added dependency 'c' to b
+u: Unit[b] (deps: [c]) @
+Never encountered 'b' before, caching...
+Stored unit Unit[b] (deps: [c]) @
+u: Unit[c] (deps: []) @
+Never encountered 'c' before, caching...
+Stored unit Unit[c] (deps: []) @
+Unit 'a' has 1 dependencies that must be met
+Unit 'b' has 1 dependencies that must be met
+Unit 'c' has 0 dependencies that must be met
+Were all 0 dependencies satisfied for 'c'?: true
+Starting up 'c'...
+Added 'c' to the run queue
+b.u.command: /bin/ping
+Installed 0 environment variables for c
+Process PID 3698030 for 'c'...
+Started task Unit[c] (deps: []) @
+
+ Manager state
+
+ Cache: map[a:Unit[a] (deps: [b]) @ b:Unit[b] (deps: [c]) @ c:Unit[c] (deps: []) @ ]
+
+ Pending: map[]
+
+ Running: map[c:main.LoadedUnit[c] (state: 0)]
+
+ Failed: TODO: Add failed queue
+
+Satisfied dependency 'c' for 'b'
+Were all 1 dependencies satisfied for 'b'?: true
+Starting up 'b'...
+Added 'b' to the run queue
+b.u.command: /bin/yes
+Installed 0 environment variables for b
+Process PID 3698031 for 'b'...
+Started task Unit[b] (deps: [c]) @
+
+ Manager state
+
+ Cache: map[a:Unit[a] (deps: [b]) @ b:Unit[b] (deps: [c]) @ c:Unit[c] (deps: []) @ ]
+
+ Pending: map[]
+
+ Running: map[b:main.LoadedUnit[b] (state: 0) c:main.LoadedUnit[c] (state: 0)]
+
+ Failed: TODO: Add failed queue
+
+Satisfied dependency 'b' for 'a'
+Were all 1 dependencies satisfied for 'a'?: true
+Starting up 'a'...
+Added 'a' to the run queue
+b.u.command: /bin/yes
+Installed 0 environment variables for a
+HJDJhdjkfhfjkdhjksdfhsdfjk
+HJDJhdjkfhfjkdhjksdfhsdfjk
+HJDJhdjkfhfjkdhjksdfhsdfjk
+Log monitor for 'b' on fd '&{0xc000180240}' enter
+HJDJhdjkfhfjkdhjksdfhsdfjk
+Log monitor for 'c' on fd '&{0xc000180120}' enter
+HJDJhdjkfhfjkdhjksdfhsdfjk
+Log monitor for '%!s(int=1000)' on fd '%!v(MISSING)' using buffer size %!d(MISSING)
+Log monitor for '%!s(int=1000)' on fd '%!v(MISSING)' using buffer size %!d(MISSING)
+HJDJhdjkfhfjkdhjksdfhsdfjk
+HJDJhdjkfhfjkdhjksdfhsdfjk
+Log monitor for 'c' on fd '&{0xc000180060}' enter
+HJDJhdjkfhfjkdhjksdfhsdfjk
+Log monitor for '%!s(int=1000)' on fd '%!v(MISSING)' using buffer size %!d(MISSING)
+Log monitor for 'a' on fd '&{0xc000180480}' enter
+HJDJhdjkfhfjkdhjksdfhsdfjk
+Log monitor for '%!s(int=1000)' on fd '%!v(MISSING)' using buffer size %!d(MISSING)
+Log monitor for 'b' on fd '&{0xc000180300}' enter
+HJDJhdjkfhfjkdhjksdfhsdfjk
+Log monitor for '%!s(int=1000)' on fd '%!v(MISSING)' using buffer size %!d(MISSING)
+HJDJhdjkfhfjkdhjksdfhsdfjk
+Log monitor for 'a' on fd '&{0xc000180540}' enter
+HJDJhdjkfhfjkdhjksdfhsdfjk
+Log monitor for '%!s(int=1000)' on fd '%!v(MISSING)' using buffer size %!d(MISSING)
+Got 32 bytes: '/bin/yes: invalid option -- 'c'
+'
+Got 32 bytes: 'Try '/bin/yes --help' for more i'
+Got 12 bytes: 'nformation.
+'
+Log monitor error returned whilst reading: EOF
+Log monitor for 'b' on fd '&{0xc000180240}' exit
+Log monitor error returned whilst reading: EOF
+Log monitor for 'b' on fd '&{0xc000180300}' exit
+Process PID 3698032 for 'a'...
+Started task Unit[a] (deps: [b]) @
+
+ Manager state
+
+ Cache: map[a:Unit[a] (deps: [b]) @ b:Unit[b] (deps: [c]) @ c:Unit[c] (deps: []) @ ]
+
+ Pending: map[]
+
+ Running: map[a:main.LoadedUnit[a] (state: 0) b:main.LoadedUnit[b] (state: 0) c:main.LoadedUnit[c] (state: 0)]
+
+ Failed: TODO: Add failed queue
+
+Unit 'a' was immediately satisfied
+Got 76 bytes: '/bin/yes: invalid option -- 'c'
+Try '/bin/yes --help' for more information.
+'
+Log monitor error returned whilst reading: EOF
+Log monitor for 'a' on fd '&{0xc000180540}' exit
+Log monitor error returned whilst reading: EOF
+Log monitor for 'a' on fd '&{0xc000180480}' exit
+Got 111 bytes: 'PING bing.com (2620:1ec:33:1::10) 56 data bytes
+64 bytes from 2620:1ec:33:1::10: icmp_seq=1 ttl=54 time=186 ms
+'
+Got 63 bytes: '64 bytes from 2620:1ec:33:1::10: icmp_seq=2 ttl=54 time=187 ms
+'
+Got 63 bytes: '64 bytes from 2620:1ec:33:1::10: icmp_seq=3 ttl=54 time=187 ms
+'
+Log monitor error returned whilst reading: EOF
+Log monitor for 'c' on fd '&{0xc000180120}' exit
+Got 63 bytes: '64 bytes from 2620:1ec:33:1::10: icmp_seq=4 ttl=54 time=187 ms
+'
+Got 63 bytes: '
+--- bing.com ping statistics ---
+4 packets transmitted, 4 rece'
+Got 63 bytes: 'ived, 0% packet loss, time 2999ms
+rtt min/avg/max/mdev = 186.30'
+Got 27 bytes: '9/186.881/187.140/0.337 ms
+'
+Log monitor error returned whilst reading: EOF
+Log monitor for 'c' on fd '&{0xc000180060}' exit
+signal: interrupt
+FAIL new.git.deavmi.assigned.network/deavmi/worcesterinit.git 7.271s

Served by rngit 1.5.0 - Generated in 0.17s